package org.design.factoryPattern;

import org.junit.Test;

/**
 * AbstractFactoryPattern
 * 抽象工厂模式
 * 抽象工厂模式（Abstract Factory Pattern）是围绕一个超级工厂创建其他工厂。
 * 该超级工厂又称为其他工厂的工厂。
 * 这种类型的设计模式属于创建型模式，它提供了一种创建对象的最佳方式。
 * 在抽象工厂模式中，接口是负责创建一个相关对象的工厂，不需要显式指定它们的类。
 * 每个生成的工厂都能按照工厂模式提供对象。
 * 抽象工厂模式提供了一种创建一系列相关或相互依赖对象的接口，而无需指定具体实现类。
 * 通过使用抽象工厂模式，可以将客户端与具体产品的创建过程解耦，使得客户端可以通过工厂接口来创建一族产品。
 *
 * @author 樊温军
 * @date 2025/6/11 上午9:55
 */
public class AbstractFactoryPattern {
    public interface Shape {
        void draw();
    }

    public class Rectangle implements Shape {

        @Override
        public void draw() {
            System.out.println("内部—长方形：draw（）方法。");
        }
    }

    public class Square implements Shape {

        @Override
        public void draw() {
            System.out.println("内部—正方形：draw（）方法。");
        }
    }

    public class Circle implements Shape {

        @Override
        public void draw() {
            System.out.println("内部—园形：draw（）方法。");
        }
    }

    public interface Color {
        void fill();
    }

    public class Red implements Color {

        @Override
        public void fill() {
            System.out.println("内部—红色：fill（）方法。");
        }
    }

    public class Green implements Color {

        @Override
        public void fill() {
            System.out.println("内部—绿色：fill（）方法。");
        }
    }

    public class Blue implements Color {

        @Override
        public void fill() {
            System.out.println("内部—蓝色：fill（）方法。");
        }
    }

    public abstract class AbstractFactory {
        public abstract Color getColor(ColorType color);

        public abstract Shape getShape(ShapeType shape);
    }

    public class ShapeFactory extends AbstractFactory {

        @Override
        public Shape getShape(ShapeType shapeType) {
            if (shapeType == null) {
                return null;
            }
            if (shapeType.equals(ShapeType.CIRCLE)) {
                return new Circle();
            } else if (shapeType.equals(ShapeType.RECTANGLE)) {
                return new Rectangle();
            } else if (shapeType.equals(ShapeType.SQUARE)) {
                return new Square();
            }
            return null;
        }

        @Override
        public Color getColor(ColorType color) {
            return null;
        }
    }

    public class ColorFactory extends AbstractFactory {

        @Override
        public Shape getShape(ShapeType shapeType) {
            return null;
        }

        @Override
        public Color getColor(ColorType color) {
            if (color == null) {
                return null;
            }
            if (color.equals(ColorType.RED)) {
                return new Red();
            } else if (color.equals(ColorType.GREEN)) {
                return new Green();
            } else if (color.equals(ColorType.BLUE)) {
                return new Blue();
            }
            return null;
        }
    }

    public class FactoryProducer {
        public AbstractFactory getFactory(FactoryType choice) {
            if (choice.equals(FactoryType.SHAPE)) {
                return new ShapeFactory();
            } else if (choice.equals(FactoryType.COLOR)) {
                return new ColorFactory();
            }
            return null;
        }
    }

    public enum FactoryType {
        SHAPE, COLOR;
    }

    public enum ShapeType {
        CIRCLE, RECTANGLE, SQUARE;
    }

    public enum ColorType {
        RED, GREEN, BLUE;
    }

    @Test
    public void test() {
        FactoryProducer factoryProducer = new FactoryProducer();
        AbstractFactory shapeFactory = factoryProducer.getFactory(FactoryType.SHAPE);
        Shape shape = shapeFactory.getShape(ShapeType.CIRCLE);
        shape.draw();
        AbstractFactory colorFactory = factoryProducer.getFactory(FactoryType.COLOR);
        Color color = colorFactory.getColor(ColorType.RED);
        color.fill();
    }
}
